import * as ExcelJS from 'exceljs';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { connect } from 'http2';
import Connection from 'mysql2/typings/mysql/lib/Connection';
import {
  Between,
  getConnection,
  getRepository,
  Not,
  Repository,
} from 'typeorm';
import {
  CreateErrorLianluDto,
  ErrorLianluListDto,
  ExportExcelDto,
  QueryListDto,
} from './dto/errorLianlu.dto';
import { ErrorLianlu } from './errorLianlu.entity';

@Injectable()
export class ErrorLianluService {
  constructor(
    @InjectRepository(ErrorLianlu)
    private dailyInfoRepository: Repository<ErrorLianlu>,
  ) {}

  // 分页、按条件获取数据
  async getErrorLianluList(queryData: QueryListDto) {
    if (queryData.recordDateStart === '') {
      queryData.recordDateStart = '1000/01/01';
      queryData.recordDateEnd = '3000/01/01';
    }
    const result = await getRepository(ErrorLianlu).find({
      skip: (queryData.pageNumber - 1) * queryData.pageSize,
      take: queryData.pageSize,
      where: {
        record_date: Between(
          new Date(queryData.recordDateStart),
          new Date(queryData.recordDateEnd),
        ),
        // record_date: {from:queryData.recordDateStart, to:queryData.recordDateEnd}
      },
      order: {
        record_date: 'DESC',
      },
    });
    return result;
  }

  // 获取错误链路的总条数
  async getErrorLianluCount(queryData: QueryListDto) {
    if (queryData.recordDateStart === '') {
      queryData.recordDateStart = '1000/01/01';
      queryData.recordDateEnd = '3000/01/01';
    }
    const result = await getRepository(ErrorLianlu).find({
      where: {
        record_date: Between(
          new Date(queryData.recordDateStart),
          new Date(queryData.recordDateEnd),
        ),
        // record_date: {from:queryData.recordDateStart, to:queryData.recordDateEnd}
      },
    });
    return result.length;
  }

  // 获取同一天的异常链路的数量
  async getErrorLianluNumber() {
    const result = await getConnection()
      .createQueryRunner()
      .query(
        'select record_date, COUNT(*) number from error_lianlu GROUP BY record_date ORDER BY record_date',
      );
    return result;
  }

  // 根据id获取异常链路信息
  async getErrorLianluById(id: string) {
    const result = await getConnection()
      .getRepository(ErrorLianlu)
      .createQueryBuilder()
      .where('id = :id', { id })
      .getOne();
    return result;
  }

  // 新增异常链路信息
  async addErrorLianlu(data: CreateErrorLianluDto[]) {
    const result = await getConnection()
      .createQueryBuilder()
      .insert()
      .into(ErrorLianlu)
      .values(data)
      .execute();
    return result;
  }

  // 删除异常链路信息
  async delErrorLianlu(id: string) {
    const result = await getConnection()
      .createQueryBuilder()
      .delete()
      .from(ErrorLianlu)
      .where('id = :id', { id })
      .execute();
    return result;
  }

  // 修改链路信息
  async updataLianlu(id: string, data: CreateErrorLianluDto) {
    const result = await getConnection()
      .createQueryBuilder()
      .update(ErrorLianlu)
      .set(data)
      .where('id = :id', { id })
      .execute();
    return result;
  }

  // 导出异常链路信息
  async exportExcle(data: ExportExcelDto): Promise<ArrayBuffer> {
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet('excel表格');
    // 定义表头名称和字段名
    worksheet.columns = [
      { header: '链路编号', key: 'lianlu_code', width: 16 },
      { header: '链路名称', key: 'lianlu_name', width: 16 },
      { header: '源端数据库', key: 'lianlu_start', width: 22 },
      { header: '目标端数据库', key: 'lianlu_end', width: 22 },
      { header: '问题发现时间', key: 'error_time_find', width: 22 },
      { header: '问题修复时间', key: 'error_time_solve', width: 22 },
      { header: '问题简要原因', key: 'error_reason', width: 50 },
      { header: '计划内升级或故障', key: 'plan_error', width: 17 },
      { header: '日期', key: 'record_date', width: 12 },
    ];
    /**
     * 格式化时间
     * @params time: string 需要转换的时间（可以被Date()转换为时间对象就可以）
     * @params format: string 需要转换成的格式 yyyy/MM/dd hh:mm:ss
     */
    const formatTime = function (time: string | Date, format: string) {
      const date = new Date(time);
      const year = String(date.getFullYear());
      const month = String(date.getMonth() + 1);
      const day = String(date.getDate());
      const hour = String(date.getHours());
      const minute = String(date.getMinutes());
      const second = String(date.getSeconds());
      // 查找需要转化格式中的各个字符的个数
      const yearNumber = getCharCount(format, 'y');
      const monthNumber = getCharCount(format, 'M');
      const dayNumber = getCharCount(format, 'd');
      const hourNumber = getCharCount(format, 'h');
      const minuteNumber = getCharCount(format, 'm');
      const secondNumber = getCharCount(format, 's');
      let resTimeStr = '';
      resTimeStr +=
        yearNumber === 0
          ? ''
          : yearNumber === 2
          ? year.slice(-2) + '/'
          : year + '/';
      resTimeStr +=
        monthNumber === 0
          ? ''
          : monthNumber === 2
          ? month.padStart(2, '0') + '/'
          : month + '/';
      resTimeStr +=
        dayNumber === 0
          ? ''
          : dayNumber === 2
          ? day.padStart(2, '0') + ' '
          : day + ' ';
      resTimeStr +=
        hourNumber === 0
          ? ''
          : hourNumber === 2
          ? hour.padStart(2, '0') + ':'
          : hour + ':';
      resTimeStr +=
        minuteNumber === 0
          ? ''
          : minuteNumber === 2
          ? minute.padStart(2, '0') + ':'
          : minute + ':';
      resTimeStr +=
        secondNumber === 0
          ? ''
          : secondNumber === 2
          ? second.padStart(2, '0')
          : second;
      return resTimeStr;
    };
    // 查找一个字符串种含有某个字符的个数
    const getCharCount = function (str: string, char: string) {
      const strArr = str.split(char);
      return str.length === 0 ? 0 : strArr.length - 1;
    };
    // const result = []; // result是通过前端传递的ids从数据库获取需要导出的信息
    if (data.recordDateStart === '') {
      data.recordDateStart = '1000/01/01';
      data.recordDateEnd = '3000/01/01';
    }
    const result: ErrorLianluListDto[] = await getRepository(ErrorLianlu).find({
      where: {
        record_date: Between(
          new Date(data.recordDateStart),
          new Date(data.recordDateEnd),
        ),
      },
      order: {
        record_date: 'ASC',
      },
    });
    result.forEach((item) => {
      item.error_time_find =
        item.error_time_start === ''
          ? ''
          : formatTime(item.error_time_start, 'yyyy/MM/dd hh:mm:ss');
      item.error_time_solve =
        item.error_time_end === ''
          ? ''
          : formatTime(item.error_time_end, 'yyyy/MM/dd hh:mm:ss');
    });

    worksheet.addRows(result);
    return workbook.xlsx.writeBuffer(); // 前端接受到的数据格式为{type: 'buffer', data: []}
  }
}
